﻿using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace yysAuxiliary.FS
{
    /// <summary>
    /// 获取操作坐标
    /// </summary>
    public class OperationPoint
    {
        public enum OperationType
        {
            [Description("经验条")]
            JYT = 0,
            [Description("探索")]
            TanSuo,
            [Description("御魂")]
            YuHun,
            [Description("八岐大蛇")]
            BQDS,
            [Description("十层")]
            ShiCeng,
            [Description("悲鸣")]
            BeiMing,
            [Description("挑战")]
            TiaoZhan,
            [Description("返回")]
            FanHui,
            [Description("关闭")]
            GuanBi,
            [Description("结算")]
            JS,
            [Description("悬赏协助弹出")]
            XSXZTC,
            [Description("悬赏接受")]
            XSJS,
            [Description("悬赏拒绝")]
            XSJJ,
            [Description("失败")]
            SB,
            [Description("战斗状态")]
            ZDZT,
            [Description("准备")]
            ZB,


            [Description("业原火")]
            YYH_YYH,
            [Description("业原火痴之阵")]
            YYH_CZZ,

            [Description("结界突破")]
            JJTP,
            [Description("结界突破进攻")]
            JJTP_JG,
            [Description("结界突破刷新")]
            JJTP_SX,
            [Description("结界未打")]
            JJTP_WD,
            [Description("结界列表失败")]
            JJTP_LBSB,
            [Description("结界突破失败")]
            JJTP_SB,
            [Description("结界突破星星")]
            JJTP_XX,
            [Description("结界突破卷不够")]
            JJTP_JBG
        }

        static OperationPoint()
        {
            Assembly myAssem = Assembly.GetExecutingAssembly();
            ResourceManager rm = new ResourceManager("yysAuxiliary.Properties.Resources", myAssem);
            var resources = rm.GetResourceSet(CultureInfo.CurrentCulture, true, true).OfType<DictionaryEntry>();
            if (!Directory.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pic")))
            {
                Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pic"));
            }
            var AllImages =
              System.IO.Directory.EnumerateFiles(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pic")).Where(p => p.ToLower().EndsWith(".png")).Select(p => p).ToList();

            var type = typeof(OperationType);
            foreach (var item in type.GetEnumValues())
            {
                var attrs = item.GetType().GetField(item.ToString())
                    .GetCustomAttributes(typeof(DescriptionAttribute), true);
                string desc = string.Empty;
                if (attrs != null && attrs.Length > 0)
                {
                    DescriptionAttribute descAttr = attrs[0] as DescriptionAttribute;
                    desc = descAttr.Description;
                }
                List<Bitmap> bitmaps = new List<Bitmap>();
                bitmaps.AddRange(resources.Where(p => p.Key.ToString().StartsWith(desc) && (p.Value is Bitmap)).Select(p => p.Value as Bitmap).ToList());
                bitmaps.AddRange(AllImages.Where(p => p.Split('\\').Last().StartsWith(desc)).Select(p => new Bitmap(p)).ToList());
                dicPath.Add((OperationType)item, bitmaps);
            }

        }

        //public readonly static List<string> AllImages =
        //    System.IO.Directory.EnumerateFiles(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pic")).Where(p => p.ToLower().EndsWith(".png")).Select(p => p).ToList();

        public readonly static Dictionary<OperationType, List<Bitmap>> dicPath = new Dictionary<OperationType, List<Bitmap>>();
        //{
        //    {OperationType.JYT,AllImages.Where(p=>p.Split('\\').Last().StartsWith("经验条")).Select(p=>new Bitmap(p)).ToList() },
        //    {OperationType.TanSuo, AllImages.Where(p=>p.Split('\\').Last().StartsWith("探索")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.YuHun,AllImages.Where(p=>p.Split('\\').Last().StartsWith("御魂")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.BQDS, AllImages.Where(p=>p.Split('\\').Last().StartsWith("八岐大蛇")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.ShiCeng, AllImages.Where(p=>p.Split('\\').Last().StartsWith("十层")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.BeiMing, AllImages.Where(p=>p.Split('\\').Last().StartsWith("悲鸣")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.TiaoZhan, AllImages.Where(p=>p.Split('\\').Last().StartsWith("挑战")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.FanHui,AllImages.Where(p=>p.Split('\\').Last().StartsWith("返回")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.GuanBi,AllImages.Where(p=>p.Split('\\').Last().StartsWith("关闭")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JS,AllImages.Where(p=>p.Split('\\').Last().StartsWith("结算")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.XSXZTC,AllImages.Where(p=>p.Split('\\').Last().StartsWith("悬赏协助弹出")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.XSJS,AllImages.Where(p=>p.Split('\\').Last().StartsWith("悬赏接受")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.XSJJ,AllImages.Where(p=>p.Split('\\').Last().StartsWith("悬赏拒绝")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.SB,AllImages.Where(p=>p.Split('\\').Last().StartsWith("失败")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.ZDZT, AllImages.Where(p=>p.Split('\\').Last().StartsWith("战斗状态")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.ZB, AllImages.Where(p=>p.Split('\\').Last().StartsWith("准备")).Select(p=>new Bitmap(p)).ToList()},

        //    {OperationType.YYH_YYH, AllImages.Where(p=>p.Split('\\').Last().StartsWith("业原火")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.YYH_CZJ, AllImages.Where(p=>p.Split('\\').Last().StartsWith("业原火痴之卷")).Select(p=>new Bitmap(p)).ToList()},


        //    {OperationType.JJTP, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界突破")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JJTP_JG, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界突破进攻")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JJTP_SX, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界突破刷新")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JJTP_WD, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界未打")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JJTP_LBSB, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界列表失败")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JJTP_SB, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界突破失败")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JJTP_XX, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界突破星星")).Select(p=>new Bitmap(p)).ToList()},
        //    {OperationType.JJTP_JBG, AllImages.Where(p=>p.Split('\\').Last().StartsWith("结界突破卷不够")).Select(p=>new Bitmap(p)).ToList()},


        //};


        /// <summary>
        /// 获取坐标
        /// </summary>
        /// <param name="source"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static Point GetPoint(Bitmap source, OperationType type)
        {
            Point point = new Point();
            foreach (var item in dicPath[type])
            {
                point = PicContain(source, item);
                if (point.X != 0 && point.Y != 0)
                    return point;
            }
            return point;
        }

        public static Point GetPoint(OperationType type)
        {
            using (var image = WinHelper.GetBitmap())
            {
                return GetPoint(image, type);
            }

        }

        /// <summary>
        /// 循环点击
        /// </summary>
        /// <param name="whileCount">循环次数</param>
        /// <param name="whilemillisecondsDelay">循环间隔</param>
        /// <param name="type"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        public static bool WhileCheck(int whileCount, int whilemillisecondsDelay, OperationType type, int offset = 0)
        {
            int n = 0;
            while (n < whileCount)
            {
                var result = IsExisit(type);
                if (result.isExisit)
                {
                    WinHelper.SendCheck(result.point, offset);
                    return true;
                }
                n++;
                Task.Delay(whilemillisecondsDelay).Wait();
            }
            return false;
        }

        /// <summary>
        /// 存在并点击
        /// </summary>
        /// <param name="type"></param>
        /// <param name="offset"></param>
        /// <param name="handleXSTK">处理悬赏弹框</param>
        /// <returns></returns>
        public static bool ExisitWithCheck(OperationType type, int offset = 0, bool handleXSTK = true)
        {
            //实现方式，1.先处判断悬赏弹框,2.处理程序要处理的类型
            if (handleXSTK)
                HandleXSTK();
            var result = IsExisit(type);
            if (result.isExisit)
            {
                WinHelper.SendCheck(result.point, offset);

            }
            return result.isExisit;
        }


        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="source"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static (bool isExisit, Point point) IsExisit(OperationType type)
        {
            var p = GetPoint(type);
            if (p.X == 0 && p.Y == 0)
            {
                return (false, p);
            }
            return (true, p);
        }

        /// <summary>
        /// 悬赏弹框处理
        /// </summary>
        private static void HandleXSTK()
        {
            var result = ExisitWithCheck(OperationType.XSXZTC, 20, false);
            if (result)
            {
                ExisitWithCheck(OperationType.XSJJ, 5, false);
            }
        }

        /// <summary>
        /// 是否存在
        /// </summary>
        /// <param name="source"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        //[Obsolete("不使用，会照成内存飙升")]
        //public static (bool isExisit, Point point) IsExisit(Bitmap source, OperationType type)
        //{
        //    var p = GetPoint(source, type);
        //    if (p.X == 0 && p.Y == 0)
        //    {
        //        return (false, p);
        //    }
        //    return (true, p);

        //}




        /// <summary>
        /// 图片包含 不存在就返回 0,0
        /// </summary>
        /// <param name="source">源图片</param>
        /// <param name="son">子图片需要包含验证</param>
        /// <returns></returns>
        private static Point PicContain(Bitmap source, Bitmap son)
        {
            Image<Bgr, byte> fu = new Image<Bgr, byte>(source);
            Image<Bgr, byte> zi = new Image<Bgr, byte>(son);
            Image<Gray, float> c = new Image<Gray, float>(fu.Width, fu.Height);
            c = fu.MatchTemplate(zi, TemplateMatchingType.CcorrNormed);
            double min = 0, max = 0;
            Point maxp = new Point(0, 0);
            Point minp = new Point(0, 0);
            CvInvoke.MinMaxLoc(c, ref min, ref max, ref minp, ref maxp);//max值需要大于0.98以上

            fu.Dispose();
            zi.Dispose();
            c.Dispose();
            if (max > Data.Threshold)
                return maxp;
            else
                return new Point(0, 0);
        }

        /// <summary>
        /// 图片包含 不存在就返回 0,0
        /// </summary>
        /// <param name="source">源图片</param>
        /// <param name="path">子图片地址</param>
        /// <returns></returns>
        private static Point PicContain(Bitmap source, string path)
        {
            Image<Bgr, byte> fu = new Image<Bgr, byte>(source);
            Image<Bgr, byte> zi = new Image<Bgr, byte>(path);
            Image<Gray, float> c = new Image<Gray, float>(fu.Width, fu.Height);
            c = fu.MatchTemplate(zi, TemplateMatchingType.CcorrNormed);
            double min = 0, max = 0;
            Point maxp = new Point(0, 0);
            Point minp = new Point(0, 0);
            CvInvoke.MinMaxLoc(c, ref min, ref max, ref minp, ref maxp);//max值需要大于0.98以上
            if (max > Data.Threshold)
                return maxp;
            else
                return new Point(0, 0);
        }
    }

}
